---
sidebar_position: 2
title: Request
sidebar_label: Request
---

<div class="api-link">
  <div class="api-link-title">Request</div>
  <div class="api-link-sub-title">

[Read the API Reference »](/api/Hyper-Fetch/Class/Request.mdx)

  </div>
</div>

---

## Introduction

**`Request`** is a class that creates a template for requests and all the necessary information needed for their
creation. Its strength is its strict and predictable data structure. This lets us dump data, save it to storage as a
JSON, and recreate it later. This approach allows you to develop a full persistence flow; you can easily persist request
dumps between sessions.

`Request` contains information about its behavior in the queues or cache, data on the server, and information necessary
to execute a valid request. In combination with TypeScript, this results in a very friendly flow that’s resistant to
mistakes.

You can trigger a request with the `send` method, which adds a request to the queue and returns the response.

---

## Purpose

- Configures request templates
- Standardizes the system’s data schema
- Sends requests via dispatchers

---

## Related guides

- [Parameters](/guides/01-basic/parameters.mdx)
- [Query Parameters](/guides/01-basic/query-params.mdx)
- [Payload](/guides/01-basic/payload.mdx)
- [Dispatching](/guides/01-basic/dispatching.mdx)
- [Retries](/guides/01-basic/retries.mdx)
- [Error handling](/guides/01-basic/error-handling.mdx)
- [Data mapping](/guides/01-basic/data-mapping.mdx)
- [Validation](/guides/02-advanced/validation.mdx)
- [Mapping](/guides/02-advanced/mapping.mdx)
- [Deduplication](/guides/02-advanced/deduplication.mdx)
- [Queueing](/guides/02-advanced/queueing.mdx)

---

## Initialization

Request should be initialized from the Client instance with `createRequest` method. This passes a shared reference to
the place that manages communication in the application.

:::caution

Hyper Fetch currently uses currying in the `createRequest` method to achieve auto-generated types for the endpoint
string. This solution will be changed once [this TypeScript issue](https://github.com/microsoft/TypeScript/issues/10571)
is resolved.

:::

---

## Options

Request contains all the necessary information to make a request. We can use it later to send them with already prepared
setup saving time and improving our architecture.

`Options are crucial to the successful data exchange.` We have to provide at least the `endpoint` to fulfill minimum
requirements.

#### Here you can find some examples of possible configurations.

{/* (@import HyperFetch RequestOptionsType type=returns) */}

### You can also provide options to the adapter

:::info

Adapter options may vary depending on the adapter you use.

:::

Default HTTP adapter options:

```ts
{
  timeout: number;
  withCredentials: boolean;
  responseType: "text" | "document" | "arraybuffer" | "blob" | "json";
}
```

Add them by:

```ts
const request = client.createRequest()({
  endpoint: "/some-endpoint",
  options: { timeout: 1000, withCredentials: true },
});
```

---

## Request building

### Initialize

The process begins with request initialization. At this point, you can configure how the request will behave, but most
of the configurations are optional. You can also prepare a global configuration in the Client and avoid copying the
setup between requests.

```ts
type ResponseType = { success: boolean }
type PayloadDataType = { name: string }

const postUser = client.createRequest<ResponseType, PayloadDataType>()({
  endpoint: "/some-endpoint",
  headers: {},
  auth: true,
  method: "POST"
  cancelable: false,
  retry: 2,
  retryTime: 1000,
});

const { data, error } = await postUser.send({ data: { name: "Maciej" } })
```

### Request Data

Use the `setData` method to instruct any data to be sent to the server.

```ts
// Regular data
postUser.setData({ name: "John", age: 18 })

// Form data
const data = new FormData();
...
postFile.setData(data)
```

### Parameters

Parameters must be defined in request endpoint using `:`

```ts
const getNote = client.createRequest()({
  endpoint: "/note/:noteId";
})
const getCategory = client.createRequest()({
  endpoint: "/category/:categoryId";
})
const getCategoryNote = client.createRequest()({
  endpoint: "/category/:noteId";
})
```

When you have properly prepared requests that expect parameters, you can add parameters using the `setParams` method. In
generic TypeScript, these parameters will match the endpoint parameters by using literal types and will require literal
types.

```tsx
getNote.setParams({ noteId: 1 });
getCategory.setParams({ categoryId: 2 });
getCategoryNote.setParams({ categoryId: 2, noteId: 1 });
```

### Query parameters

You can set query params with the `setQueryParams` method. With TypeScript, you can set it up to be accepted as strings,
objects, or a strict interface. The encoding type for arrays and other options can be set up in the Client. You can also
provide your own encoding logic.

```tsx
getUsers.setQueryParams({ search: "John", sort: "age" });
```

### Trigger request

You can perform a request with the `send` method.

```tsx
// Simple Send
getNotes.send();

// Chained Send
getUsers.setQueryParams({ search: "John", sort: "age" }).send();

// Multiple chained Send
const { data, error } = await getCategory.setParams({ categoryId: 2 }).setQueryParams({ sortNotes: "age" }).send();
```

#### For usage with **`React`** checkout our [hooks docs](/documentation/04-react/01-overview.mdx).

---

## Features

You can read more in the API reference and guides.

### [Cancellation](/guides/02-advanced/cancellation.mdx)

### [Queueing](/guides/02-advanced/queueing.mdx)

### [Offline](/guides/02-advanced/offline.mdx)

### [Deduplication](/guides/02-advanced/deduplication.mdx)

### [Authentication](/guides/01-basic/authentication.mdx)

### [Data Mapping](/guides/01-basic/data-mapping.mdx)

---

## Methods

Using methods on a request is different from other classes in Hyper Fetch. This is to ensure isolation between different
uses, which allows you to avoid overwriting previously-prepared requests and to dynamically generate keys for queues or
the cache.

:::danger

Using any method on request returns its clone! `We don't return a reference!`

:::

```tsx
// ❌ WRONG

const request = getUser;

request.setParams({ userId: 1 }); // Returns CLONED request with assigned params

const { data, error } = await request.send(); // Server error - no params
```

```tsx
// ✅ Good

const request = getUser;

const requestWithParams = request.setParams({ userId: 1 }); // Returns CLONED request with assigned params

const { data, error } = await requestWithParams.send(); // Success
```

---

## Keys

Each request gets its identifiers – `queueKey`, `cacheKey`, `abortKey`, and `effectKey`. They are needed to determine
under which key items will be cached, queued, canceled or handled by [Effects](/documentation/02-core/effect.mdx). By
default, keys are auto-generated based on the current parameters and endpoint and method values. However, you can
overwrite these values with other methods as needed.

---

## Typescript

Client has four generic types built in: `Response`, `Payload`, `Local Error Response`, and `QueryParams`.

```tsx
type Response = { name: string }; // What's returned from request
type Payload = { email: string }; // What's send with request
type LocalError = { nameMessage: string }; // Additional "local" errors like errors for particular form
type QueryParams = { sort: string; search: string }; // Query params interface

const someRequest = client.createRequest<Response, Payload, LocalError, QueryParams>()({
  endpoint: "category/:categoryId",
});

someRequest.setData(); // Require the 'Payload' type
someRequest.setParams(); // Require { categoryId: Param } type
someRequest.setQueryParams(); // Require the 'QueryParams' type

const { data, error } = someRequest.send();

data; // Has 'Response' type
error; // Has 'GlobalError' or 'LocalError' type
```

---

## Usage

```tsx
import { client } from "./client";

export const getUsers = client.createRequest<UserModel[]>()({
  method: "GET",
  endpoint: "/users",
});

export const getUser = client.createRequest<UserModel>()({
  method: "GET",
  endpoint: "/users/:userId",
});

export const postUser = client.createRequest<UserModel, UserPostDataType>()({
  method: "POST",
  endpoint: "/users",
});

export const patchUser = client.createRequest<UserModel, Partial<UserPostDataType>>()({
  method: "PATCH",
  endpoint: "/users/:userId",
});

export const deleteUser = client.createRequest<null>()({
  method: "DELETE",
  endpoint: "/users/:userId",
});

// Usage

const { data, error } = await getUsers.send({ queryParams: { page: 1 } });

const { data, error } = await getUsers.send({ params: { userId: 23 } });

const { data, error } = await postUser.send({ data: { name: "Maciej" } });

const { data, error } = await patchUser.send({ params: { userId: 12 }, data: { name: "Kacper" } });

const { data, error } = await deleteUser.send({ params: { userId: 88 } });
```

---

## Lifecycle listeners

We can easily add lifecycle listeners to the **`send()`** method. This allows us to listen to the request events and
perform callbacks with the received data for each stage of execution.

{/* (@import HyperFetch FetchSendActionsType type=returns) */}

#### Example

```tsx
await request.send({
  onSettle: (requestId) => {
    console.log(requestId);
  },
});
```

---

## Parameters

Configuration options for the `client.createRequest()` method.

{/* (@import HyperFetch RequestOptionsType type=returns) */}

#### Example

```tsx
const request = client.createRequest()({
  endpoint: "/some-endpoint",
  retry: 2,
  cancelable: true,
  cacheTime: 20000,
  cacheKey: "users",
  deduplication: true,
});
```
